//
// DBInterface.h
// libprotea
// Tools Library for the Protea Project / Database-Independent Interface
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
// 
// Please send correspondence to:
// 
// theproteaproject@gmail.com
//

#ifndef __PROTEA_DBINTERFACE_H__
#define __PROTEA_DBINTERFACE_H__

/**
	\file DBInterface.h
	\brief Definition of database interface class
	
	XCDBInterface class definition

	This class is essentially just the interface definition of all the database drivers.
	All drivers are of class name DBI{database name}.
*/


#include "Database.h"

// copy of relevant field flags from validation.cpp
#define FLAG_ALLOW_NULL 512


// Enumeration for non-buffer statement types
enum mem_type
{
	mem_long,
	mem_char
};

// Declarations
class XCDBInterface;
class XCDBTransaction;
class XCDBStatement;
class XCDBConnection;
class XCSQLStatement;

// Database Interface Base Class
//
// Interface definition for object representing individual SQL database interface
/////////////////////////////////////////////////////////////////////////////////

/*
	Interface definition for object representing individual SQL database interface

	Database interfaces all derive from the pure virtual class.
*/
class __EXPORT XCDBInterface : public XCBase 
{
public:
	/// Constructor
	virtual ~XCDBInterface() {};

/*
	// Copy constructor
	XCDBInterface( XCDBInterface& copy ) {
		// Cause a fault
		int *p = 0;
		*p = 0;
	};
*/
	// Supported by all drivers
	///////////////////////////

	// connections

	// Initiate a connection
	virtual XCDBConnection* Connect(const char* uid, const char* pass) = 0;

	// Optionally supported by drivers
	//////////////////////////////////

	// Create a new database
	virtual void CreateDB(char* name, XCDBTransaction* txn) = 0;

	// Open the database in exclusive mode
	virtual void OpenExclusive() = 0;

	// Return information on current connected users
	virtual void UserInfo() = 0;

	// Returns the database descriptor information
	virtual XCDBDriverDescr* GetDatabaseInfo() = 0;

	// ptr to parent connection object
	XCAppInterface* myapp;
	XCDBInterface* dbi;
	XCDBHandlerConnection* parent;
};


// Connection Base Class
//
// Each thread/user needs to own an open database connection.  Database txns are one
// per connection
class __EXPORT XCDBConnection : public XCBase
{
public:
	// Close an open connection
	virtual void Disconnect() = 0;

	// Create a transaction
	virtual XCDBTransaction* CreateTxn() = 0;

	// Refresh a connection
	virtual bool Refresh() = 0;
};



// Transaction Base Class
//
// Interface definition for object representing individual SQL transactions
/////////////////////////////////////////////////////////////////////////////////


// Interface definition for object representing individual SQL transactions
class __EXPORT XCDBTransaction : public XCBase
{
	friend class XCTxn;

public:
	XCDBTransaction() { started = false; };

	/// Destructor
	virtual ~XCDBTransaction() {};

	/// Start a connection with the given isolation level
	virtual void Begin(isolevel il = serializable) = 0;

	/// Commit the current transaction
	virtual void Commit() = 0;

	/// Rollback the current transaction
	virtual void Rollback() = 0;

	/// Create a statement within the transaction
	virtual XCDBStatement* CreateStmt(XCBuffer* buf) = 0;

	/// Create a statement within the transaction based on existing XCSQLGen
	virtual XCDBStatement* CreateStmt2(XCSQLGen* query) = 0;

	/// Get the associated database number
	virtual long GetDatabaseNumber() = 0;

	/// Prepare a transaction (two-phase commit)
	virtual void Prepare() = 0;

	/// Database locking
	virtual void LockTable( XCBuffer* table, XCField* value ) = 0;

protected:
	bool started;
};


struct SQLStmtIndexer {
	XCField* field;
};



// Statement Base Class
//
// Interface definition for object representing individual SQL statements
/////////////////////////////////////////////////////////////////////////////////

/// Interface definition for object representing individual SQL statements
class __EXPORT XCDBStatement : public XCSQLGen
{
	friend class XCTxn;

public:
	/// Constructor
	XCDBStatement();

	XCDBStatement( XCAppInterface *app );

	XCDBStatement( XCSQLGen *qry );

	/// Destructor
	virtual ~XCDBStatement();

	/// Destroy this statement
	virtual void Release() = 0;

	// Execute a SQL statement, return "true" for SELECT, "false" otherwise
	virtual bool Execute(char* sqlstr) = 0;	

	virtual bool Execute() = 0;

	virtual bool MakeStmt() = 0;

	/// Move to next record in bound SELECT statement
	virtual void MoveNext() = 0;

	/// Returns end of file flag
	virtual bool Eof() = 0;

	/// Returns the SQL string currently associated with this statement (with parameter binding)
	virtual char* GetSQLString() = 0;

	/// Places the SQL string with the parameters filled in into the buffer passed to it
	virtual char* GetSQLString( char* buffer) = 0;

	static int counter;
};


// SQL Statement Base Class
//
// Generates an actual SQL statement based on a given XCSQLGen class
////////////////////////////////////////////////////////////////////
#define	MAX_SQL_LEN	32768

class __EXPORT XCSQLStatement : public XCBase
{
public:
	XCSQLStatement();
	XCSQLStatement( XCSQLGen *qry );
	XCSQLStatement( XCPrepSQLGen* qry );

	/** /brief Generate an actual SQL statement out of the supplied XCSQLGen.
		
		Returns a (const) pointer to the sql string generated.
	*/

	const char *MakeStatement();

protected:

	// functions that are used to make the statement, they may be overriden in the
	// individual drivers

	void Clear();
	void ClearIndexers();
	void MakeSELECT();
	virtual void MakeINSERT();
	void MakeDELETE();
	void MakeUPDATE();
	void MakeCOUNT();
	void AddWHERE();
	void AddORDERBY();
	void MakeFull( char* buffer = NULL );
	void SetQuery( XCSQLGen *new_query );
	void SetQuery( XCPrepSQLGen* new_query );
	long AddPredicate( char* result, XCCompare* comp);
	long AddJOIN( char* result, XCJoin* join);
	long AddTableList( char* result );

	virtual int GetSelectValue(XCField* fld, bool joins, char* start);
	virtual int GetValue(XCField* fld, char* start = NULL);
	virtual int GetValueNoParam(XCField* fld, char* start = NULL);	
	virtual void GetFullString( char* buffer );

	
	XCSQLGen *query;
	char sql_data[ MAX_SQL_LEN ];
	char *data;
	bool params;
	bool reset;

	SQLStmtIndexer* ColIndexer;
	int ColCount;
	SQLStmtIndexer* ParamIndexer;
	int ParamCount;
	void AddToParamIndexer( XCField* fld );

	// 
	// Stuff for prep functionality
	//

	XCPrepSQLGen* pquery;	// special query for prep functions

	// the definition for these functions is in prepSQL.cpp not in DBInterface.cpp with the rest of them
	int GetFullDataType( XCField* fld, char* start, bool table );
	virtual int GetDefault( XCField* fld, char* start );

	virtual char *FixString( XCField* fld );
	virtual int GetDataType( XCField* fld, char* start, bool& do_not_null );
	virtual int AddCON( char* start );
	virtual int DropCON( char* start );
	void MakeCREATE();
	virtual void CreateAUTONUMBER();
	virtual void RemoveAUTONUMBER();
	void MakeDROP();
	void MakeALTER();
	virtual void MakeRENAME();
};



// Locates and opens the shared library associated with the specified db_type
__EXPORT XCDBInterface* GetDBInterface( db_type type, XCSharedLibrary* dynamic, XCDBHandlerConnection* dbcon, XCAppInterface* app );

// Closes the shared library
__EXPORT void XCDeleteDBInterface( XCSharedLibrary* dynamic );



#endif
